package org.needcoke.hs.signature;

import cn.hutool.core.util.StrUtil;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.needcoke.hs.util.ClassUtil;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@ToString(callSuper = true)
public class ConfigSignature extends AbstractSignature {

    @Override
    public void setSortedFunction(String functionName) {
        if (StrUtil.isEmpty(functionName)) {
            return;
        }
        SortedFunction sortedFunction = sortedFunctionMap.get(functionName);
        if (null == sortedFunction) {
            Class<?> clz = ClassUtil.forName(functionName);
            sortedFunction = (SortedFunction) ClassUtil.instance(clz);
        }
        this.setSortedFunction(sortedFunction);
    }

    @Override
    public void setSignFunction(String functionName) {
        if (StrUtil.isEmpty(functionName)) {
            return;
        }
        SignFunction signFunction = signFunctionMap.get(functionName);

        if (null == signFunction) {
            Class<?> clz = ClassUtil.forName(functionName);
            signFunction = (SignFunction) ClassUtil.instance(clz);
        }
        this.setSignFunction(signFunction);
    }

    public void setSignatureLocation(String location) {
        if ("header".equals(location)) {
            this.setSignatureLocation(SignatureLocation.HTTP_HEADER);
            return;
        }
        if ("param".equals(location)) {
            this.setSignatureLocation(SignatureLocation.HTTP_URL_PARAM);
        }
    }

    @Override
    public void setSignCode(String sc) {
        if (StrUtil.isEmpty(sc)) {
            return;
        }
        this.signCode = signCodeMap.get(sc);
    }

    public void setBodyBefore(String bodyBefore) {
        this.bodyBefore = Boolean.getBoolean(bodyBefore);
    }



    public void setWithFormBody(String doNotWithFormBody) {
        this.withFormBody = !Boolean.getBoolean(doNotWithFormBody);
    }

    public void setWithApplicationBody(String doNotWithApplicationBody) {
        this.withApplicationBody =  !Boolean.getBoolean(doNotWithApplicationBody);
    }

    @Override
    public Signature copy() {
        ConfigSignature signature = new ConfigSignature();
        signature.setSignFunction(signFunction);
        signature.setSortedFunction(sortedFunction);
        signature.setProof(proof, proofEnd);
        signature.setSignCode(signCode);
        signature.setConnectorBetweenNameAndValue(connectorBetweenNameAndValue);
        signature.setConnectorBetweenTwoGroup(connectorBetweenTwoGroup);
        signature.setConnectorBetweenBodyAndParam(connectorBetweenBodyAndParam);
        signature.setInterceptRule(null == interceptRule ? null : interceptRule.copy());
        signature.setSignatureLocation(signatureLocation);
        signature.setSignatureName(signatureName);
        signature.setWithFormBody(withFormBody);
        signature.setWithApplicationBody(withApplicationBody);
        signature.setBodyBefore(bodyBefore);
        signature.setPrefix(prefix);
        signature.setSuffix(suffix);
        signature.setAround(around);
        signature.setSignKey(signKey);
        signature.addParam(params);
        if (StrUtil.isNotEmpty(signatureName)) {
            signature.params.remove(signatureName);
        }
        return signature;
    }

    private static final Map<String, SortedFunction> sortedFunctionMap;

    private static final Map<String, SignFunction> signFunctionMap;

    private static final Map<String, SignCode> signCodeMap;


    static {
        sortedFunctionMap = new HashMap<>();
        sortedFunctionMap.put("default", SortedFunction.defaultSortedFunction);
        sortedFunctionMap.put("string-asc", SortedFunction.defaultSortedFunction);
        sortedFunctionMap.put("string-desc", SortedFunction.stringDescSortedFunction);

        signFunctionMap = new HashMap<>();
        signFunctionMap.put("default", SignFunction.defaultSignFunction);
        signFunctionMap.put("md5", SignFunction.defaultSignFunction);
        signFunctionMap.put("sha256", SignFunction.sha256SignFunction);
        signFunctionMap.put("rsa2", SignFunction.rsa2SignFunction);
        signFunctionMap.put("rsa", SignFunction.rsaSignFunction);


        signCodeMap = new HashMap<>();
        signCodeMap.put("default", SignCode.HEX);
        signCodeMap.put("NO", SignCode.NO);
        signCodeMap.put("BASE64", SignCode.BASE64);
        signCodeMap.put("HEX", SignCode.HEX);
    }
}
